package com.probiz.estore.system.dao.impl;

import java.util.Date;

import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.SessionFactoryUtils;

import com.probiz.estore.common.helper.ConfigUtil;
import com.probiz.estore.common.model.system.AppUser;
import com.probiz.estore.core.dao.impl.HibernateGenericDaoImpl;
import com.probiz.estore.core.util.StringUtil;
import com.probiz.estore.system.dao.AppUserDao;
import com.probiz.estore.webapp.util.RequestContext;

/**
 * Dao implementation for AppUser.
*/
public class AppUserDaoImpl<T extends AppUser> extends HibernateGenericDaoImpl<T> implements AppUserDao<T>, UserDetailsService{
	
	
	public T getUserByName(String username) {
        String hql="";
    	if(username.indexOf("@")!=-1){
        	hql="from "+ entityClass.getName() +" where email=?";
        }else{
        	hql="from "+ entityClass.getName() +" where username=?";
        }
    	T user = (T) findUnique(hql,username);

        return user;
    }
	/*
     * (non-Javadoc)
     * 
     * @see org.acegisecurity.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
     */
    public UserDetails loadUserByUsername(final String username)
            throws UsernameNotFoundException, DataAccessException {
        try {
            return (UserDetails) getHibernateTemplate().execute(
                    new HibernateCallback() {
                        public Object doInHibernate(Session session) {
                        	String hql="";
                        	boolean isFrontStore=RequestContext.isFront();
                        	if(username.indexOf("@")!=-1){
                        		hql="from "+ entityClass.getName() +" where email=?";
                        	}else{
                        		hql="from "+ entityClass.getName() +" where username=?";
                        	}
                        	if(!isFrontStore){
                        		hql+=" and userType="+AppUser.USER_TYPE_ADMIN;
                        	}
                            Query queryObject = session
                                    .createQuery(hql);
                            
                            SessionFactoryUtils.applyTransactionTimeout(
                                    queryObject, session.getSessionFactory());
                            queryObject.setParameter(0, username);

                            T user = (T) queryObject.uniqueResult();
                            if (user != null) {
                                Hibernate.initialize(user.getUserRoles());
                            }
                            return user;
                        }
                    }, true);
        } catch (Exception e) {
            throw new UsernameNotFoundException("user '" + username
                    + "' not found...", e);
        }
    }

    public boolean isUserExist(String username) {
        Long userCount = this.countByHql("from AppUser where username=?", username);
        if (userCount != null && userCount==0) {
            logger.debug("the username has not in database,so can use for register!");
            return false;
        } else {
            return true;
        }
    }

    /**
     * is email exist?
     * 
     * @param email
     */
    public boolean isEmailExist(String email) {
        Long userCount = this.countByHql(" from AppUser where email=?", email);
        if (userCount != null && userCount==0) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * is email use by others?
     * 
     * @param email
     * @param myAppuserId
     */
    public boolean getIsEmailUseByOthers(String email, Integer myAppuserId) {
        String hql = "select count(*) from AppUser where email =:email and appuserId<>:appuserId";

        //int countNumber=getJdbcTemplate().queryForInt("select count(*) from
        // app_user where email = '"+email+"' and appuserId!=" + myAppuserId);
        Query query = getSession().createQuery(hql);

        query.setString("email", email);
        query.setInteger("appuserId", myAppuserId.intValue());
        int countNumber = ((Long) query.uniqueResult()).intValue();

        if (countNumber > 0) {
            if (logger.isDebugEnabled()) {
                logger.debug("email use by others!");
            }
            return true;
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("email not use by others!");
            }
            return false;
        }
    }

    /**
     * modify password by email
     */
    public boolean modifyPasswordByEmail(String email, String newPassword) {
        String hql = "update "+ entityClass.getName() +" set password=? where email=?";
        Query query = getSession().createQuery(hql);

        query.setString(0, newPassword);
        query.setString(1, email);

        int rows = query.executeUpdate();
        if (rows > 0)
            return true;
        else
            return false;
    }

    /**
     * @see AppUserDAO#saveAppUserStatusByEmail(String, Short)
     */
    public void saveAppUserStatusByEmail(String email, Short status) {

        String hql = "update "+ entityClass.getName() +" set status=? where email=?";
        Query query = getSession().createQuery(hql);
        query.setShort(0, status.shortValue());
        query.setString(1, email);
        query.executeUpdate();

    }

    /**
     * modify password by appuserId
     */
    public void modifyPasswordByAppuserId(Integer appuserId, String newPassword) {
    	newPassword = StringUtil.encodePassword(newPassword, ConfigUtil.getInstance().getPasswordEncryptionAlgorithm());
        String hql = "update "+ entityClass.getName() +" set password=? where appuserId=?";
        Query query = getSession().createQuery(hql);

        query.setString(0, newPassword);
        query.setInteger(1, appuserId.intValue());

        query.executeUpdate();
    }
    
    public void saveLastLoginTimeByAppuserId(Integer appuserId, Date lastLoginTime) {
        String hql="update "+ entityClass.getName() +" set lastLoginTime=? where appuserId=?";
        Query query=getSession().createQuery(hql);
        query.setDate(0,lastLoginTime);
        query.setInteger(1,appuserId.intValue());
        query.executeUpdate();
    }
       
}
